/*
HitoeProfileECGFragment
Copyright (c) 2016 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.deviceplugin.hitoe.fragment;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.achartengine.GraphicalView;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.deviceconnect.android.deviceplugin.hitoe.HitoeApplication;
import org.deviceconnect.android.deviceplugin.hitoe.R;
import org.deviceconnect.android.deviceplugin.hitoe.activity.HitoeDeviceControlActivity;
import org.deviceconnect.android.deviceplugin.hitoe.data.HeartRateData;
import org.deviceconnect.android.deviceplugin.hitoe.data.HitoeConstants;
import org.deviceconnect.android.deviceplugin.hitoe.data.HitoeDevice;
import org.deviceconnect.android.deviceplugin.hitoe.data.HitoeManager;
import org.deviceconnect.android.deviceplugin.hitoe.util.HitoeScheduler;
import java.util.ArrayList;
import java.util.List;
/**
* This fragment do setting of the control ECG profile.
*
* @author NTT DOCOMO, INC.
*/
public class HitoeProfileECGFragment extends Fragment implements HitoeScheduler.OnRegularNotify {
/** Title size. */
public static final int CHART_TITLE_SIZE = 25;
/** Label size. */
public static final int LABELS_SIZE = 16;
/** Axis Title. */
public static final int AXIS_TITLE_SIZE = 25;
/** Axis color. */
public static final int AXIS_COLOR = Color.GRAY;
/** Grid color. */
public static final int GRID_COLOR = Color.GRAY;
/** Title color. */
public static final int TITLE_COLOR = Color.GRAY;
/** x label color. */
public static final int XLABEL_COLOR = Color.GRAY;
/** y label color. */
public static final int YLABEL_COLOR = Color.GRAY;
/** data count. */
private static final int DATA_COUNT = 1;
/** orientation title. */
private static final String[] TITLES = new String[] {"ECG" };
/** data color. */
private static final int[] COLORS = new int[] {Color.GREEN };
/** data count. */
private static final long MAX_RANGE = 10000;
/** ECG. */
private List<XYSeries> mECGList = null;
/** Graph data . */
private LineChart mLineChart;
/** Graph view. */
private GraphicalView mGraphicalView;
/** Graph render. */
private XYMultipleSeriesRenderer mXYMultipleSeriesRenderer;
/** min data. */
private long mMinX = 0;
/** max data. */
private long mMaxX = mMinX + MAX_RANGE;
/**
* Current Hitoe Device object.
*/
private HitoeDevice mCurrentDevice;
/**
* Hitoe Scheduler.
*/
private HitoeScheduler mScheduler;
@Override
public View onCreateView(final LayoutInflater inflater, final @Nullable ViewGroup container,
final @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_ecg_instructions, null);
mScheduler = new HitoeScheduler(this, HitoeConstants.ACC_CHART_UPDATE_CYCLE_TIME,
HitoeConstants.ACC_CHART_UPDATE_CYCLE_TIME);
rootView.findViewById(R.id.button_register).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
clear();
mScheduler.scanHitoeDevice(true);
}
});
rootView.findViewById(R.id.button_unregister).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
mScheduler.scanHitoeDevice(false);
}
});
TextView title = (TextView) rootView.findViewById(R.id.view_title);
Bundle args = getArguments();
if (args != null) {
String serviceId = args.getString(HitoeDeviceControlActivity.FEATURE_SERVICE_ID);
HitoeApplication app = (HitoeApplication) getActivity().getApplication();
HitoeManager manager = app.getHitoeManager();
mCurrentDevice = manager.getHitoeDeviceForServiceId(serviceId);
if (mCurrentDevice != null) {
String[] profiles = getResources().getStringArray(R.array.support_profiles);
title.setText(profiles[3] + getString(R.string.title_control));
}
}
init();
((LinearLayout) rootView.findViewById(R.id.ecg_chart)).addView(mGraphicalView);
return rootView;
}
@Override
public void onDestroy() {
super.onDestroy();
mScheduler.scanHitoeDevice(false);
}
@Override
public void onRegularNotify() {
if (getActivity() == null) {
return;
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
HitoeApplication app = (HitoeApplication) getActivity().getApplication();
HitoeManager manager = app.getHitoeManager();
HeartRateData ecg = manager.getECGData(mCurrentDevice.getId());
if (ecg != null) {
setECG(ecg.getECG().getTimeStamp(), ecg.getECG().getValue());
updateChart();
}
}
});
}
/**
* Initialize ECG chart.
*/
private void init() {
this.mECGList = new ArrayList<>();
this.mECGList.add(new XYSeries(TITLES[0]));
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addAllSeries(this.mECGList);
this.mXYMultipleSeriesRenderer = buildRenderer();
mLineChart = new LineChart(dataset, mXYMultipleSeriesRenderer);
mGraphicalView = new GraphicalView(getActivity(), mLineChart);
}
/**
* Set ECG data.
* @param timestamp timestamp
* @param ecg ecg data
*/
private void setECG(final long timestamp, final double ecg) {
if (mECGList.get(0).getItemCount() == 0) {
mMinX = timestamp;
mMaxX = timestamp + MAX_RANGE;
}
if (timestamp > mMaxX || mECGList.get(0).getItemCount() > MAX_RANGE / 40) {
this.mECGList.get(0).clear();
mMinX = timestamp;
mMaxX = timestamp + MAX_RANGE;
}
mECGList.get(0).add(timestamp, ecg / 1000);
}
/**
* Update chart.
*/
private void updateChart() {
mXYMultipleSeriesRenderer.setXAxisMin(mMinX);
mXYMultipleSeriesRenderer.setXAxisMax(mMaxX);
mGraphicalView.repaint();
}
/**
* Clear chart.
*/
private void clear() {
this.mECGList.get(0).clear();
mGraphicalView.repaint();
}
/**
* Build ECG Chart renderer.
* @return ecg chart renderer
*/
private XYMultipleSeriesRenderer buildRenderer() {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
for (int i = 0; i < DATA_COUNT; i++) {
XYSeriesRenderer r = new XYSeriesRenderer();
r.setColor(COLORS[i]);
r.setLineWidth(4f);
r.setPointStyle(PointStyle.CIRCLE);
r.setFillPoints(true);
r.setPointStrokeWidth(1f);
renderer.addSeriesRenderer(r);
}
renderer.setPointSize(1f);
renderer.setChartTitle("心電");
renderer.setChartTitleTextSize(CHART_TITLE_SIZE);
renderer.setXTitle("経過時間 [ms]");
renderer.setYTitle(" [μv]");
renderer.setLabelsTextSize(LABELS_SIZE);
renderer.setLabelsColor(TITLE_COLOR);
renderer.setXLabelsAlign(Paint.Align.LEFT);
renderer.setYLabelsAlign(Paint.Align.RIGHT);
renderer.setXLabelsColor(XLABEL_COLOR);
renderer.setYLabelsColor(0, YLABEL_COLOR);
renderer.setAxisTitleTextSize(AXIS_TITLE_SIZE);
renderer.setAxesColor(AXIS_COLOR);
renderer.setXAxisMin(mMinX);
renderer.setXAxisMax(mMaxX);
renderer.setYAxisMin(-3.0);
renderer.setYAxisMax(3.0);
renderer.setShowGridX(true);
renderer.setShowGridY(true);
renderer.setGridColor(GRID_COLOR);
renderer.setApplyBackgroundColor(true);
renderer.setBackgroundColor(Color.BLACK);
renderer.setMargins(new int[] {16, 48, 16, 8 });
renderer.setMarginsColor(Color.argb(0, 255, 255, 255));
renderer.setPanEnabled(false, false);
renderer.setShowLegend(true);
renderer.setLegendTextSize(15);
renderer.setFitLegend(false);
renderer.setZoomButtonsVisible(false);
renderer.setZoomEnabled(false, false);
return renderer;
}
}